/**
 * 
 */
package multidomain;

import java.util.Iterator;
import java.util.Vector;

import controlPlane.OBGPSpeaker;
import controlPlane.PCE;
import wdmsim.Flow;
import wdmsim.Node;
import wdmsim.OXC;

/**
 * @author alissonslp
 *
 */
public class Domain {

	private int id;
	private static Vector<Domain> domains = null;
	private Vector<OXC> nodes = null;
	private PCE pce;
	//private MultidomainVirtualTopology vt;
	private String rwaMode;
	//private ControlPlane controlPlane;
	//private IntradomainControlPlane controlPlane;
	//private String rwaModule;
	//private String rwaParameters;
	private int load;
	private int maxRate;
	private int numCalls;
	
	public Domain( int id, /*String rwaModule, String rwaParameter, String rwaMode,*/ int load, int maxRate) {
		this.id = id;
		/*this.rwaModule = new String(rwaModule);
		this.rwaParameters = new String(rwaParameter);
		this.rwaMode = new String(rwaMode);*/
		this.load = load;
		this.maxRate = maxRate;
		
		this.nodes = new Vector<OXC>();
		
		try {
			addDomain(this);
		} catch (Exception e) {
			e.printStackTrace();
		}		
	}
	
	/**
	 * @throws Exception 
	 * 
	 */
	public static void processPCEs() throws Exception {
		Domain domain;
		Iterator<Domain> it;
		
		it = domains.iterator();
		while(it.hasNext()) {
			domain = it.next();
			//if(domain.getRwaMode().matches("pce-based")) {
				domain.newPCE();
			//}	
		}		
	}
	
	/**
	 * 
	 */
	public static void processOBGPSpeekers() {
		// TODO Auto-generated method stub
		Domain domain;
		Iterator<Domain> it;
		
		it = domains.iterator();
		while(it.hasNext()) {
			domain = it.next();
			//if(domain.getRwaMode().matches("pce-based")) {
				
			//}	
		}	
		
	}
	
	public int getLoad() {
		return load;
	}

	public void setLoad(int load) {
		this.load = load;
	}

	public int getMaxRate() {
		return maxRate;
	}

	public void setMaxRate(int maxRate) {
		this.maxRate = maxRate;
	}

	public int getNumCalls() {
		return numCalls;
	}

	public void setNumCalls(int numCalls) {
		this.numCalls = numCalls;
	}

	/**
	 * @throws Exception 
	 * 
	 */
	private void newPCE() throws Exception {		
		pce = new PCE(this.id);
	}

	private static void addDomain(Domain newDomain) throws Exception {
		Domain domain;
		if (domains == null)
			domains = new Vector<Domain>();
		
		Iterator<Domain> it = domains.iterator(); // para verificar se já tem dominio com o mesmo id 
		while (it.hasNext()) {
			domain = it.next();
			if (domain.getID() == newDomain.getID()) {
				throw(new Exception("Dois dominios com ID " + domain.getID()));
			}
		}
		domains.add(newDomain);	
	}
	
	public static Domain getDomainByID(int id) {
		Iterator<Domain> it = domains.iterator();
		Domain d;
		
		while (it.hasNext()) {
			d = (Domain) it.next();
			if (d.getID() == id) 
				return(d);				
		}
		
		return(null);
	}
	
	/**
	 * @return id
	 */
	public int getID() {		
		return id;
	}

	public PCE getPce() {
		return pce;
	}

	public void setPce(PCE pce) {
		this.pce = pce;
	}

	/**
	 * 
	 */
	public static void initiateDomainsStructures() {
		Domain domain;
		Iterator<Domain> it;
		
		it = domains.iterator();
		while(it.hasNext()) {
			domain = it.next();
			domain.initiateStructures();
		}
	}
	
	/**
	 * 
	 */
	private void initiateStructures() {
		//vt = new MultidomainVirtualTopology(id);
		try {
			createNewControlPlane();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		
	}

	/**
	 * @throws Exception 
	 * 
	 */
	private void createNewControlPlane() throws Exception {
		Vector<OXC> nodes = getNodes();
		for(int i=0; i<getNumNodes(); i++) {
			OXC oxc = nodes.get(i);
			if(oxc instanceof OBGPSpeaker) {
				((OBGPSpeaker)oxc).generateRIB(oxc.getId());
			}
		}
		
	}
	
	public boolean nodeBelongsToDomain(int id) {
		Iterator<OXC> it = nodes.iterator();
		OXC node;
		
		while (it.hasNext()) {
			node = it.next();
			if (node.getId() == id)
				return(true);
		}
		return(false);
	}
	
	public void addNode(OXC node) {
		if (!nodeBelongsToDomain(node.getId()))
			nodes.add(node);
	}
	
	public int getNumNodes() {
		return(nodes.size());
	}
	
	public String getRwaMode() {
		return rwaMode;
	}

	public void setRwaMode(String rwaMode) {
		this.rwaMode = rwaMode;
	}
	
	public Vector<OXC> getNodes() {
		return nodes;
	}
	
	public OXC getNode(int i) {
		return nodes.get(i);
	}

	public void setNodes(Vector<OXC> nodes) {
		this.nodes = nodes;
	}
	
	public OBGPSpeaker getOBGPSPeaker() {
		for(int i=0; i<getNumNodes(); i++) {
			if(getNode(i) instanceof OBGPSpeaker) {
				return (OBGPSpeaker)getNode(i);
			}
		}
		return null;
	}
	
	/* The method below was created to avoid problems in multiple runs.
	 * Once the "domains" variable is a static, in multiple runs it mantains
	 * the domains add. So, it is necessary to clear before continue running.*/
	public static void clearStaticVariables() {
		if (domains != null)
			domains.clear();
	}

	/**
	 * 
	 */
	public void acceptFlow(Flow flow) {
		this.pce.activeFlow(flow);
		
	}

}
